﻿#region License

/*
 © 2012 Alex Kazaev
 * FolderDrive project [http://folderdrive.codeplex.com/]
 * Licensed under Ms-PL license [http://www.opensource.org/licenses/MS-PL]
 */

#endregion License

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Windows;
using FolderDrive.Core;

namespace FolderDrive.ViewModels
{
  /// <summary>
  /// Main view model class for the FolderDrive application
  /// </summary>
  public class FolderDriveViewModel : BaseViewModel
  {
    #region fields

    private readonly ObservableCollection<MappingPreferenceItem> mappingItems =
      new ObservableCollection<MappingPreferenceItem>();

    private FolderDriveStates currentState = FolderDriveStates.MappingGrid;
    private bool isAllChecked;
    private AddMappingViewModel mappingViewModel = new AddMappingViewModel();
    private readonly OptionsViewModel optionsViewModel = new OptionsViewModel();
    private Visibility updateVisibility;

    #endregion fields

    #region properties

    public Visibility UpdateVisibility
    {
      get { return updateVisibility; }
      set
      {
        updateVisibility = value;
        NotifyChanged("UpdateVisibility");
      }
    }

    /// <summary>
    /// Gets a value indicating whether the is toolbar enabled.
    /// </summary>
    /// <value>
    /// <c>true</c> if the toolbar is enabled; otherwise, <c>false</c>.
    /// </value>
    public bool IsToolbarEnabled
    {
      get { return currentState == FolderDriveStates.MappingGrid; }
    }

    /// <summary>
    /// Gets the mapping grid visibility.
    /// </summary>
    public Visibility MappingGridVisibility
    {
      get { return currentState == FolderDriveStates.MappingGrid ? Visibility.Visible : Visibility.Hidden; }
    }

    /// <summary>
    /// Gets the add mapping control visibility.
    /// </summary>
    public Visibility AddMappingVisibility
    {
      get { return currentState == FolderDriveStates.AddMapping ? Visibility.Visible : Visibility.Hidden; }
    }

    /// <summary>
    /// Gets the info control visibility.
    /// </summary>
    public Visibility InfoVisibility
    {
      get { return currentState == FolderDriveStates.Info ? Visibility.Visible : Visibility.Hidden; }
    }

    /// <summary>
    /// Gets the options control visibility.
    /// </summary>
    public Visibility OptionsVisibility
    {
      get { return currentState == FolderDriveStates.Options ? Visibility.Visible : Visibility.Hidden; }
    }

    /// <summary>
    /// Gets the add mapping view model.
    /// </summary>
    public AddMappingViewModel MappingViewModel
    {
      get { return mappingViewModel; }
      private set
      {
        mappingViewModel = value;
        NotifyChanged("MappingViewModel");
      }
    }

    /// <summary>
    /// Gets the options view model.
    /// </summary>
    public OptionsViewModel OptionsViewModel
    {
      get { return optionsViewModel; }
    }

    /// <summary>
    /// Gets or sets a value indicating whether all checkboxes in the grid are checked.
    /// </summary>
    /// <value>
    ///   <c>true</c> if [all checked]; otherwise, <c>false</c>.
    /// </value>
    public bool AllChecked
    {
      get { return isAllChecked; }
      set
      {
        isAllChecked = value;
        foreach (MappingPreferenceItem item in MappingItems)
        {
          item.Selected = value;
        }
        NotifyChanged("AllChecked");
        NotifyChanged("MappingItems");
      }
    }

    /// <summary>
    /// Gets the mapping items.
    /// </summary>
    public ObservableCollection<MappingPreferenceItem> MappingItems
    {
      get { return mappingItems; }
    }

    #endregion properties

    #region constructor

    /// <summary>
    /// Initializes a new instance of the <see cref="FolderDriveViewModel"/> class.
    /// </summary>
    public FolderDriveViewModel()
    {
      var config = Configuration.FolderDriveConfigurationManager.GetDriveMappings();
      foreach (var item in config)
      {
        FolderDosDevice.MapDrive(item.Key, item.Value);
        MappingItems.Add(new MappingPreferenceItem(item.Key, item.Value, Configuration.FolderDriveConfigurationManager.GetPermanentFlag(item.Key)));
      }
      UpdateVisibility = Configuration.FolderDriveConfigurationManager.GetCheckUpdates() && UpdateService.GetUpdateData() ? Visibility.Visible : Visibility.Collapsed;
    }

    #endregion constructor

    #region methods

    /// <summary>
    /// Adds the maping item.
    /// </summary>
    /// <param name="item">The item.</param>
    public void AddItem(MappingPreferenceItem item)
    {
      if (FolderDosDevice.MapDrive(item.DriveLetter, item.Path))
      {
        if (item.IsPermanent)
        {
          if (!FolderRegistryProcess.AddDrive(item.DriveLetter, item.Path))
          {
            item.IsPermanent = false;
          }
        }
        MappingItems.Add(item);
        Configuration.FolderDriveConfigurationManager.AddMapping(item.DriveLetter, item.Path, item.IsPermanent);
      }
    }

    /// <summary>
    /// Removes the selected mapping items.
    /// </summary>
    public void RemoveSelectedItems()
    {
      List<MappingPreferenceItem> selected = mappingItems.Where(item => item.Selected).ToList();
      foreach (MappingPreferenceItem item in selected)
      {
        FolderDosDevice.UnmapDrive(item.DriveLetter);
        if (item.IsPermanent)
        {
          FolderRegistryProcess.RemoveDrive(item.DriveLetter);
        }
        MappingItems.Remove(item);
        Configuration.FolderDriveConfigurationManager.RemoveMapping(item.DriveLetter);
      }
    }

    /// <summary>
    /// Shows the mapping grid.
    /// </summary>
    public void ShowMappingGrid()
    {
      currentState = FolderDriveStates.MappingGrid;
      UpdateVisibilityProperties();
    }

    /// <summary>
    /// Shows the add mapping control.
    /// </summary>
    public void ShowAddMapping()
    {
      currentState = FolderDriveStates.AddMapping;
      MappingViewModel = new AddMappingViewModel();
      UpdateVisibilityProperties();
    }

    /// <summary>
    /// Shows the info control.
    /// </summary>
    public void ShowInfo()
    {
      currentState = FolderDriveStates.Info;
      UpdateVisibilityProperties();
    }

    /// <summary>
    /// Shows the options control.
    /// </summary>
    public void ShowOptions()
    {
      currentState = FolderDriveStates.Options;
      UpdateVisibilityProperties();
    }

    /// <summary>
    /// Performs actions required on closing the main window
    /// </summary>
    public bool Closing(bool ForceClose = false)
    {
      bool minOnClose = Configuration.FolderDriveConfigurationManager.GetMinOnClose();
      if (minOnClose && !ForceClose)
      {
          return false;
      }

      if (OptionsViewModel.UnmountOnExit)
      {
        foreach (var mappingPreferenceItem in MappingItems)
        {
          FolderDosDevice.UnmapDrive(mappingPreferenceItem.DriveLetter);
        }
      }
      return true;
    }

    /// <summary>
    /// Gets the default state of the window at startup.
    /// </summary>
    /// <returns></returns>
    public WindowState GetDefaultWindowState()
    {
      return OptionsViewModel.StartMinimized ? WindowState.Minimized : WindowState.Normal;
    }

    /// <summary>
    /// Updates the visibility properties.
    /// </summary>
    private void UpdateVisibilityProperties()
    {
      NotifyChanged("MappingGridVisibility");
      NotifyChanged("AddMappingVisibility");
      NotifyChanged("InfoVisibility");
      NotifyChanged("OptionsVisibility");
      NotifyChanged("IsToolbarEnabled");
    }

    /// <summary>
    /// Opens the link to the release on the codeplex.
    /// </summary>
    internal void UpdateSoft()
    {
      Process.Start(UpdateService.Link);
    }

    #endregion methods
  }
}